﻿//**************************************************************
//
// MoneyBaby Project - Open source payment processors for .NET
//
// Copyright 2007-2008 Marcus McConnell and BV Software
// www.CodePlex.com/MoneyBaby
//**************************************************************

using System;
using System.Collections.Generic;
using System.Text;
using System.Web;

namespace BVSoftware.MoneyBaby.Gateways
{
    public class WorldPayJuniorSelect: BaseCreditCardGateway<WorldPayJuniorSelectGatewaySettings>
    {
        public override Guid GatewayId { get { return new Guid("0667F161-8BAB-4def-BA3D-235687245264"); } }
        public override string GatewayName { get { return "WorldPay Junior Select"; } }

        public override bool SupportsAuthorize { get { return true; } }
        public override bool SupportsCapture { get { return true; } }
        public override bool SupportsCharge { get { return true; } }
        public override bool SupportsRefund { get { return true; } }
        public override bool SupportsVoid { get { return false; } }

        internal WorldPayJuniorSelect()
        {
        }

        protected override TransactionResultData ProcessCard(PaymentOperationType operationType, PaymentData<WorldPayJuniorSelectGatewaySettings> data)
        {
            TransactionResultData result = new TransactionResultData();
            try
            {
                // Get Processor Settings                
                // NOTE: Live and test url are the same for Junior select, pass in TestMode param instead
                string liveUrl = data.GatewaySettings.UrlLive.ToString();
                string testUrl = data.GatewaySettings.UrlTest.ToString();
                if (liveUrl.Equals(string.Empty))
                {
                    liveUrl = "https://select.worldpay.com/wcc/authorise";
                }
                if (testUrl.Equals(string.Empty))
                {
                    testUrl = "https://select.worldpay.com/wcc/authorise";
                }
                // Set Server
                string serverUrl = liveUrl;
                if (data.GatewaySettings.TestMode)
                {
                    serverUrl = testUrl;
                }

                // Build Data String
                // Card Number and Expiration                
                string expMonth = string.Empty;
                // two digit month
                if (data.CardData.ExpirationMonth < 10)
                {
                    expMonth = "0" + data.CardData.ExpirationMonth.ToString();
                }
                else
                {
                    expMonth = data.CardData.ExpirationMonth.ToString();
                }

                // 4 digit year
                string expYear = string.Empty;
                expYear = data.CardData.ExpirationYear.ToString();


                // Set Parameters
                StringBuilder sb = new StringBuilder();
                string postData = string.Empty;

                sb.Append("instId=");
                sb.Append(SafeWriteString(data.GatewaySettings.Username.Trim()));

                sb.Append("&authPW=");
                sb.Append(SafeWriteString(data.GatewaySettings.Password.Trim()));
                sb.Append("&amount=");
                sb.Append(SafeWriteString(data.Transaction.Amount.ToString()));
                sb.Append("&currency=");
                sb.Append(SafeWriteString(data.GatewaySettings.CurrencyCode.Trim()));
                sb.Append("&desc=");
                sb.Append(SafeWriteString(data.Transaction.MerchantDescription.Trim()));
                sb.Append("&email=");
                sb.Append(SafeWriteString(data.Customer.EmailAddress.Trim()));
                if (data.GatewaySettings.TestMode)
                {
                    sb.Append("&amount=100");
                }

                // Customer Info
                sb.Append("&name=");
                sb.Append(SafeWriteString(data.Customer.FirstName + " " + data.Customer.LastName));
                sb.Append("&address=");
                sb.Append(SafeWriteString(data.Customer.AddressLine1 + " " + data.Customer.City + " " + data.Customer.State));
                sb.Append("&country=");
                sb.Append(SafeWriteString(data.Customer.Country));
                sb.Append("&postalcode=");
                sb.Append(SafeWriteString(data.Customer.PostalCode));
                sb.Append("&tel=");
                sb.Append(SafeWriteString(data.Customer.PhoneNumber));
                sb.Append("&fax=");
                sb.Append(SafeWriteString(data.Customer.FaxNumber));


                switch (operationType)
                {
                    case PaymentOperationType.Charge:
                        // Charge
                        sb.Append("&authMode=");
                        sb.Append(SafeWriteString("A"));
                        sb.Append("&cardname=");
                        sb.Append(SafeWriteString(data.CardData.CardHolderName.Trim()));
                        sb.Append("&cardNo=");
                        sb.Append(SafeWriteString(data.CardData.CardNumber));                        
                        sb.Append("&cardExpMonth=");
                        sb.Append(SafeWriteString(expMonth));
                        sb.Append("&cardExpYear=");
                        sb.Append(SafeWriteString(expYear));                        
                        sb.Append("&cartId=");
                        sb.Append(SafeWriteString(data.Transaction.MerchantInvoiceNumber));
                        break;
                    case PaymentOperationType.Authorize:
                        // Authorize
                       sb.Append("&authMode=");
                        sb.Append(SafeWriteString("E"));
                        sb.Append("&cardname=");
                        sb.Append(SafeWriteString(data.CardData.CardHolderName.Trim()));
                        sb.Append("&cardNo=");
                        sb.Append(SafeWriteString(data.CardData.CardNumber));                        
                        sb.Append("&cardExpMonth=");
                        sb.Append(SafeWriteString(expMonth));
                        sb.Append("&cardExpYear=");
                        sb.Append(SafeWriteString(expYear));                        
                        sb.Append("&cartId=");
                        sb.Append(SafeWriteString(data.Transaction.MerchantInvoiceNumber));
                        break;
                    case PaymentOperationType.Capture:
                        // Capture, Post Authorize
                        sb.Append("&transId=");
                        sb.Append(SafeWriteString(data.Transaction.PreviousTransactionReferenceNumber));
                        sb.Append("&op=");
                        sb.Append(SafeWriteString("postAuth-full"));                        
                        break;                  
                    case PaymentOperationType.Refund:
                        // Refund, Credit
                        sb.Append("&transId=");
                        sb.Append(SafeWriteString(data.Transaction.PreviousTransactionReferenceNumber));
                        sb.Append("&op=");
                        sb.Append(SafeWriteString("refund-partial"));
                        break;
                }

                // Dump string builder to string to send to Authorize.Net
                postData = sb.ToString();

                string responseString = Utilities.SendRequestByPost(serverUrl, postData);

                if (responseString != null)
                {
                    ParseResponse(responseString, result);
                }

            }
            catch (Exception ex)
            {
                result.Suceeded = false;
                result.Messages.Add(new TransactionMessage("Unknown Payment Error: " + ex.Message, "MBWP1001", TransactionMessageType.Error));
                result.Messages.Add(new TransactionMessage("Stack Trace " + ex.StackTrace, "STACKTRACE", TransactionMessageType.Information));
            }            
            return result;
        }

        private string SafeWriteString(string input)
        {
            return HttpUtility.UrlEncode(input);
        }

        private void ParseResponse(string responseString, TransactionResultData data)
        {
            string[] parts = responseString.Split(',');

            if (parts.Length > 2)
            {                
                data.TransactionReferenceNumber = parts[1];
                data.ResponseCode = parts[2];
                data.ResponseCodeDescription = data.ResponseCode.Replace('\n',' ');

                string approvalCode = parts[0];
                if (approvalCode.ToUpper() == "A")
                {
                    data.Suceeded = true;
                }
                else
                {
                    data.Suceeded = false;
                }
            }
            else
            {
                data.Suceeded = false;
            }            
        }
    }
}
